package com.ipan.jfinal.simpleApi;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ipan.jfinal.simpleApi.SimpleApiCounterInterceptor.CallInfo;
import com.ipan.kits.base.ExceptionUtil;
import com.ipan.kits.mapper.FastJsonMapper;
import com.ipan.kits.security.DigestUtil;
import com.ipan.kits.text.EncodeUtil;
import com.ipan.kits.text.StrFormatter;

/**
 * 简单的API接口通信工具类
 * 
 * @author iPan
 * @date 2022-06-29
 */
public final class SimpleApiManager {
	private static Logger LOG = LoggerFactory.getLogger(SimpleApiManager.class);
	private static SimpleApiEncryptAble encrypter = new SimpleApiEncryptImpl(); // 默认使用AES加密
	// 权限拦截映射器
	private static Map<String, Map<String, CallInfo>> mapping = new HashMap<>(); // userid -> map -> methodName -> count
	
	public static void setAuthHeadKey(String key) {
		AuthHead.KEY = key;
	}
	public static void setAuthHeadHead(String head) {
		AuthHead.HEAD = head;
	}
	
	public static SimpleApiEncryptAble getEncrypter() {
		return encrypter;
	}
	public static void setEncrypter(SimpleApiEncryptAble encrypter) {
		SimpleApiManager.encrypter = encrypter;
	}
	
	public static Map<String, Map<String, CallInfo>> getMethodMapping() { // 注意防止随便修改
		return mapping;
	}
	
	/**
	 * OPEN-BODY-SIG方式生成签名
	 * 
	 * 签名算法
	 * 1）json内容转二进制
	 * 2）sha256Hex加密二进制，并转小写；
	 * 3）字符串拼接“appId + timestamp + nonce + 小写的sha256Hex”
	 * 4）使用hmacSHA256加密对拼接字符串进行加密，秘钥使用appKey；
	 * 5）对加密后字节转base64
	 */
	public static String createSignature(String appId, String appKey, String timestamp, String nonce, String bodyJson) {
		Validate.notBlank(appId);
		Validate.notBlank(appKey);
		Validate.notBlank(timestamp);
		Validate.notBlank(nonce);
		Validate.notBlank(bodyJson);
		
		String result = "";
		try {
			byte[] a = bodyJson.getBytes("utf-8");
			String b = DigestUtil.sha256Hex(a).toLowerCase();
			String c = StringUtils.join(appId, timestamp, nonce, b);
			String d = appKey;
			byte[] e = DigestUtil.hmacSHA256Byte(c, d);
			result = EncodeUtil.encodeBase64(e);
		} catch(Exception e) {
			ExceptionUtil.unchecked(e);
		}
		return result;
	}
	
	/**
	 * 报文合法性校验
	 * 
	 * @param fetcher APPKEY管理者
	 * @param headAuth HTTP头部
	 * @param bodyJson HTTP正文
	 * @return true 通过 false 失败
	 */
	public static boolean validation(AppkeyFetchable fetcher, String headAuth, String bodyJson, String appkey) {
		boolean ret = false;
		String signature = null, newSignature = null;
		try {
			AuthHead head = AuthHead.parseHead(headAuth);
			signature = head.getSignature();
			newSignature = createSignature(head.getAppId(), appkey, head.getTimestamp(), head.getNonce(), bodyJson);
			ret = signature.equals(newSignature);
		} catch (Exception e) {
			LOG.error("签名校验异常", e);
			return false;
		}
		if (!ret) LOG.info(StrFormatter.format("签名校验失败，{}!={}。", signature, newSignature));
		return ret;
	}
	
	public static void main(String[] args) {
		String headAuth = "OPEN-BODY-SIG AppId=\"yh001\",Timestamp=\"20220630191239\",Nonce=\"164432653\",Signature=\"8/BfvgmbBgqFvvCnXewnwB4iiv/Z7GuDQzqeJaeoae8=\"";
		String bodyJson = "{\"userId\":\"1FDA0DAB33CB0656CC5D26E3D32124C8\",\"orgCusSendID\":\"6F4E5D0BC458AAAE3B315CD8C2F7954B\"}";
		String appkey = "2A08F8E373ECD308A5D4CC964A38CA9D";
		Map<String, Object> map = FastJsonMapper.me().jsonToMap(bodyJson);
		String userId = (String) map.get("userId");
		String newSignature = createSignature("yh001", appkey, "20220630191239", "164432653", bodyJson);
		System.out.println(newSignature);
	}
}
